//package com.yuntsg.paperana.service;
//
//import cn.hutool.db.Db;
//import cn.hutool.db.Entity;
//import co.elastic.clients.elasticsearch.ElasticsearchClient;
//import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
//import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
//import co.elastic.clients.elasticsearch._types.query_dsl.Query;
//import co.elastic.clients.elasticsearch.core.SearchRequest;
//import co.elastic.clients.elasticsearch.core.SearchResponse;
//import co.elastic.clients.elasticsearch.core.search.Hit;
//import utils.paperana.com.yuntsg.ruiijn.CharUtil;
////import com.yuntsg.paperana.utils.esutils.EsClient;
//import esutils.utils.paperana.com.yuntsg.ruiijn.EsEntity;
//import edu.stanford.nlp.ling.CoreAnnotations;
//import edu.stanford.nlp.ling.CoreLabel;
//import edu.stanford.nlp.pipeline.Annotation;
//import edu.stanford.nlp.pipeline.StanfordCoreNLP;
//import edu.stanford.nlp.util.CoreMap;
//import lombok.Data;
//import lombok.RequiredArgsConstructor;
//import lombok.SneakyThrows;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Service;
//
//import javax.annotation.Resource;
//import java.io.IOException;
//import java.sql.SQLException;
//import java.text.SimpleDateFormat;
//import java.util.*;
//
///**
// * @Author: gcr
// * @Date: 2023/8/30 15:49
// */
//@RequiredArgsConstructor(onConstructor = @__(@Autowired))
//@Service
//public class EsSearchTest {
//
//    @Resource
//    ElasticsearchClient esClient;
//
//
//    // 检索测试 2023年8月30日15:51:20
//    @SneakyThrows
//    public static void main(String[] args) {
////        String lucen = "Folate might counteract the effects of environmental chemical exposures.";
////        List<EsEntity> resultList = searchTest(lucen);
////        for (EsEntity esEntity : resultList) {
////            System.out.println(esEntity.getId());
////            System.out.println(esEntity.getStrcntest());
////            System.out.println("++++++++++++++++++++++++++");
////        }
//
//        String tableName = "pdf.pmid_pdf_sentence";
//        searchPdf(tableName);
//    }
//
//    public static void searchPdf(String tableName) throws SQLException, IOException {
//        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        System.out.println(format.format(new Date()) + " 进入程序了~~~");
//        long t0 = System.currentTimeMillis();
//        List<Entity> tableData = Db.use().query("select `paragraph_name`,`str` from " + tableName);
//        Map<Integer, StrInfo> strInfoMap = new HashMap<>();
//        int autoId = 0; // 句子的序号，类似自增主键
//        int yuanShiMax = 16; // 设定的原始最大
//        int yuanShiMin = 4; // 设定的原始最小
//        double xiangYaoMax = 1.0; // 设定的想要的最大得分
//        double xiangYaoMin = 0.5; // 设定的想要的最小得分
//        Set<Integer> hRisk = new HashSet<>(); // 高风险，匹配度大于0.8
//        Set<Integer> mRisk = new HashSet<>(); // 中风险，匹配度大于0.6
//        Set<Integer> lRisk = new HashSet<>(); // 低风险，匹配度大于0.4
//        int strSum = 0; // 测试句子的总单词数量
//        int esStrSum = 0; // 从ES检索到的句子的相同单词的数量总和
//        Map<Integer, Integer> maxArticleMap = new HashMap<>(); // 论文的Id号及重复的总次数
//        Map<Integer, List<TestStrSum>> maxArticleIdMap = new HashMap<>(); // 论文的Id号及重复的句子的信息
//
//        for (Entity entry : tableData) {
//            String paragraph_name = entry.getStr("paragraph_name");
//            String testStr = entry.getStr("str"); // 测试的句子
//            if (null != paragraph_name && null != testStr) {
//                if (paragraph_name.equals("references")) { // 参文及参文之后的内容，不再要。
//                    break;
//                }
//                String[] strSplit = testStr.split(" ");
//                List<String> strList = new ArrayList<>();
//                for (String s : strSplit) {
//                    if (s.length() > 3) { // 只保留单词的长度大于3位的单词
//                        strList.add(getLemma(s));
//                    }
//                }
//                int size = strList.size();
//                if (size > 3) {
//                    autoId++;
//                    List<EsEntity> resultList = searchTest(testStr); // ES检索返回的前10条结果
//                    int esMax = 0; // ES检索的集合中，匹配到的最多的单词的个数
//                    int esMaxSum = 0; // ES检索的集合中，匹配到的最多的单词的个数时，该句子的单词总数
//                    int esMaxId = 0;
//                    String esMaxStr = "";
//                    List<EsInfo> esList = new ArrayList<>(); // 每一条ES检索的句子的详细信息
//                    double score = 0.0;
//                    for (EsEntity esEntity : resultList) {
//                        Integer esId = esEntity.getId(); // ES检索到的文章的id号
//                        String esStr = getLemma(esEntity.getStrcntest()); // ES检索到的该文章内的一个句子
//                        String[] split = esStr.split(" ");
//                        Set<String> esSet = new HashSet<>();
//                        int esSum = 0; // ES检索到的句子，里面的单词的数量
//                        for (String s : split) {
//                            if (s.length() > 3) { // 相同的，ES检索到的句子，也只要单词长度大于3位的单词
//                                esSet.add(s);
//                                esSum++;
//                            }
//                        }
//                        int sum = getSum(strList, esSet); // 检测的句子与ES检索到的句子之间的相同的单词的个数
//
//                        double ratio = relativeValue(yuanShiMax, yuanShiMin, xiangYaoMax, xiangYaoMin, sum);
//                        double esScore = ratio * (sum + 0.0) / (size + 0.0) * (sum + 0.0) / (esSum + 0.0);
//
//                        // 最大的匹配的单词个数等，是指通过系数计算后匹配度最高的那个句子的值，而不是单单的匹配的相同的单词最多的那一个。
//                        if (esScore > score) {
//                            esMaxId = esId;
//                            esMaxStr = esStr;
//                            esMax = sum;
//                            score = esScore;
//                            esMaxSum = esSum;
//                        }
//                        EsInfo esInfo = new EsInfo();
//                        esInfo.setEsId(esId); // ES检索到的文章的id号
//                        esInfo.setEsStr(esStr); // ES检索到的该文章内的一个句子
//                        esInfo.setSum(sum); // 该句子包含的大于3位的单词个数
//                        esList.add(esInfo);
//
//                        TestStrSum testStrSum = new TestStrSum();
//                        testStrSum.setEsId(esId); // ES检索到的文章的id号
//                        testStrSum.setEsStr(esStr); // ES检索到的该文章内的一个句子
//                        testStrSum.setSum(sum); // 该句子与ES检测出来的句子相同的单词的个数
//                        testStrSum.setTestStr(testStr); // 检测的文章中的句子
//                        testStrSum.setTestId(autoId); // 检测的文章中的句子的id号
//                        maxArticleMap.compute(esId, (key, value) -> value != null ? (value + sum) : sum);
//                        maxArticleIdMap.compute(esId, (k, v) -> {
//                            if (v == null) {
//                                v = new ArrayList<>();
//                            }
//                            v.add(testStrSum);
//                            return v;
//                        });
//                    }
//                    StrInfo strInfo = new StrInfo();
//                    strInfo.setEsList(esList); // 每一条ES检索的句子的详细信息
//                    strInfo.setEsMax(esMax); // ES检索的集合中，匹配到的最多的单词的个数
//                    strInfo.setTestStr(testStr); // 测试的句子
//                    strInfo.setSum(size); // 测试的句子包含的大于3位的单词个数
//                    strInfo.setEsId(esMaxId); // ES检索中，得分最高时的ES检索到的句子ID号
//                    strInfo.setEsStr(esMaxStr); // ES检索中，得分最高时的ES检索到的句子
//                    strInfoMap.put(autoId, strInfo);
//                    strSum += size;
//                    esStrSum += esMax;
//
//                    double ratio = relativeValue(yuanShiMax, yuanShiMin, xiangYaoMax, xiangYaoMin, esMax);
//                    // 三个数值相乘后，数值比较小，故加一个系数：5.0
//                    double esScore = ratio * (esMax + 0.0) / (size + 0.0) * (esMax + 0.0) / (esMaxSum + 0.0) * 5.0;
//                    if (esScore > 0.8) { // 高风险,，匹配度大于0.8
//                        hRisk.add(autoId);
//                    } else if (esScore > 0.6) { // 中风险，匹配度大于0.6
//                        mRisk.add(autoId);
//                    } else if (esScore > 0.4) { // 低风险，匹配度大于0.4
//                        lRisk.add(autoId);
//                    }
//                }
//            }
//        }
//        double similarity = (esStrSum + 0.0) / (strSum == 0 ? 0.001 : (strSum + 0.0)); // 论文总的相似度
//        System.out.println("论文总的相似度: " + similarity);
//        println(hRisk, strInfoMap, "高风险的句子id: ");
//        println(mRisk, strInfoMap, "中风险的句子id: ");
//        println(lRisk, strInfoMap, "低风险的句子id: ");
//        Map<Integer, Integer> sortMaxArticleMap = mapSortValueLen(maxArticleMap, 1);
//        int esSum = 0;
//        for (Map.Entry<Integer, Integer> entry : sortMaxArticleMap.entrySet()) {
//            if (maxArticleIdMap.containsKey(entry.getKey())) {
//                List<TestStrSum> testStrSumList = maxArticleIdMap.get(entry.getKey());
//                String esStr = "";
//                for (TestStrSum testStrSum : testStrSumList) {
//                    String testStr = testStrSum.getTestStr();
//                    esStr = testStrSum.getEsStr();
//                    int sum = testStrSum.getSum();
//                    esSum += sum;
//                    System.out.println("相同的单词的个数： " + sum + " 测试的句子： " + testStr);
//                }
//                double esSimilarity = (esSum + 0.0) / (strSum == 0 ? 0.001 : (strSum + 0.0)); // 重复最多的ES中检索到的论文的相似度
//                System.out.println("--重复最多的ES中检索到的论文的id号: " + entry.getKey() + " 重复的单词的总个数： " + entry.getValue() + " 该篇的相似度： " + esSimilarity + " ES中检索到的句子： " + esStr);
//            }
//        }
//        long t4 = System.currentTimeMillis();
//        System.out.println(format.format(new Date()) + " 程序结束了，总用时：" + (t4 - t0));
//    }
//
//    // 比如，原始最大90，原始最小65，想要最大100，想要最小1，实际81，则：x=((实际-原始最小)*想要最大+(原始最大-实际)*想要最小)/(原始最大-原始最小)
//    public static double relativeValue(int yuanShiMax, int yuanShiMin, double xiangYaoMax, double xiangYaoMin, int shiJi) {
//        shiJi = Math.min(shiJi, yuanShiMax); // 如果实际大于原始最大，则按原始最大计算。
//        return ((shiJi - yuanShiMin) * xiangYaoMax + (yuanShiMax - shiJi) * xiangYaoMin) / (yuanShiMax - yuanShiMin);
//    }
//
//    public static void println(Set<Integer> hRisk, Map<Integer, StrInfo> strInfoMap, String info) {
//        for (Integer id : hRisk) {
//            if (strInfoMap.containsKey(id)) {
//                StrInfo strInfo = strInfoMap.get(id);
//                String testStr = strInfo.getTestStr();
//                int esId = strInfo.getEsId();
//                String esStr = strInfo.getEsStr();
//                int esMax = strInfo.getEsMax();
//                System.out.println(info + id + " 句子：" + testStr + " ES检索的集合中，匹配到的最多的单词的个数: " + esMax + " ES检索中，得分最高时的ES检索到的句子ID号: " + esId + " ES检索中，得分最高时的ES检索到的句子: " + esStr);
//            }
//        }
//    }
//
//    // 对Map进行排序，此排序为最大的在前面，输入一个map，再返回一个排序后的新map，Integer, Integer类型，本排序增加了过滤功能，可以设置要前多少（len）个。
//    public static Map<Integer, Integer> mapSortValueLen(Map<Integer, Integer> mapName, Integer len) {
//        Map<Integer, Integer> result = new LinkedHashMap<>();
//        mapName.entrySet().stream()
//                .sorted(Map.Entry.<Integer, Integer>comparingByValue()
//                        .reversed()).limit(len).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
//        return result;
//    }
//
//    public static int getSum(List<String> strList, Set<String> esSet) {
//        int sum = 0;
//        for (String s : strList) {
//            if (esSet.contains(s)) {
//                sum++;
//            }
//        }
//        return sum;
//    }
//
//    @Data
//    public static class StrInfo {
//        private List<EsInfo> esList = new ArrayList<>(); // 每一条ES检索的句子的详细信息
//        private int esId = 0; // ES检索中，得分最高时的ES检索到的句子ID号
//        private String esStr = ""; // ES检索中，得分最高时的ES检索到的句子
//        private String testStr = ""; // 测试的句子
//        private int sum = 0; // 测试的句子包含的大于3位的单词个数
//        private int esMax = 0; // ES检索的集合中，匹配到的最多的单词的个数
//    }
//
//    @Data
//    public static class TestStrSum {
//        private int esId = 0; // 检索到的文章的id号
//        private String esStr = ""; // 该文章内的一个句子
//        private String testStr = ""; // 检测的文章中的句子
//        private int testId = 0; // 检测的文章中的句子的id号
//        private int sum = 0; // 该句子与ES检测出来的句子相同的单词的个数
//    }
//
//    @Data
//    public static class EsInfo {
//        private int esId = 0; // ES检索到的文章的id号
//        private String esStr = ""; // ES检索到的该文章内的一个句子
//        private int sum = 0; // 该句子包含的大于3位的单词个数
//    }
//
//
//    // String lucen = "Folate might counteract the effects of environmental chemical exposures.";
//    public  List<EsEntity> searchTest(String lucen) throws SQLException, IOException {
//
//
////        String lucen = "Folate might counteract the effects of environmental chemical exposures.";
//        String lucen1 = "Folate might counteract the effects of environmental ";
//        String lucen2 = "Folate might counteract the effects ";
//        String lucen3 = "of environmental chemical exposures.";
//        String lucen4 = "counteract the effects of environmental chemical exposures.";
//
//        SearchRequest.Builder builder = new SearchRequest.Builder();
//        BoolQuery.Builder allQueryBuilder = new BoolQuery.Builder();
//        allQueryBuilder.must(MatchQuery.of(i -> i.field("strcntest").query(lucen))._toQuery());
//        Query query = allQueryBuilder.build()._toQuery();
//        SearchRequest searchRequest = builder.query(query)
//                .trackTotalHits(k -> k.enabled(true))
//                .from(0)
//                .size(10)
//                .build();
//
//        List<EsEntity> resultList = new ArrayList<>();
//        SearchResponse<EsEntity> response = esClient.search(searchRequest, EsEntity.class);
//        List<Hit<EsEntity>> hits = response.hits().hits();
//        for (Hit<EsEntity> hit : hits) {
//            resultList.add(hit.source());
//        }
////        for (EsEntity esEntity : resultList) {
////            System.out.println(esEntity.getId());
////            System.out.println(esEntity.getStrcntest());
////            System.out.println("++++++++++++++++++++++++++");
////        }
//        return resultList;
//
//    }
//
//
////    /**
////     * @param cla     类型
////     * @param colname 查询字段
////     * @param str     查询字符
////     * @param <T>     泛型
////     * @return 2023年8月31日16:47:23 通用查询方法
////     */
//    @SneakyThrows
////    public  <T> List<T> getSearchList(Class<T> cla, String colname, String str) {
////        ElasticsearchClient client = EsClient.client();
////        SearchRequest.Builder builder = new SearchRequest.Builder();
////        BoolQuery.Builder allQueryBuilder = new BoolQuery.Builder();
////        allQueryBuilder.must(MatchQuery.of(i -> i.field(colname).query(str))._toQuery());
////        Query query = allQueryBuilder.build()._toQuery();
////        SearchRequest searchRequest = builder.query(query)
////                .trackTotalHits(k -> k.enabled(true))
////                .from(0)
////                .size(10)
////                //.preference("_prefer_node")
////                .build();
////        List<T> resultList = new ArrayList<>();
////        SearchResponse<T> response = client.search(searchRequest, cla);
////        List<Hit<T>> hits = response.hits().hits();
////        for (Hit<T> hit : hits) {
////            resultList.add(hit.source());
////        }
////        return resultList;
////    }
//
//
//    // 斯坦福词形还原
//    public static String getLemma(String text) {
//        if (text.length() < 3) {
//            return text;
//        }
//        StringBuilder lemma = new StringBuilder();
//        Properties properties = new Properties();
//        //分词、分句、词性标注和次元信息。
//        properties.put("annotators", "tokenize,ssplit,pos,lemma");
//        StanfordCoreNLP pipeline = new StanfordCoreNLP(properties);
//        Annotation document = new Annotation(CharUtil.reKw(text));
//        pipeline.annotate(document);
//        List<CoreMap> words = document.get(CoreAnnotations.SentencesAnnotation.class);
//        for (CoreMap wordTemp : words) {
//            for (CoreLabel token : wordTemp.get(CoreAnnotations.TokensAnnotation.class)) {
//                String originalWord = token.get(CoreAnnotations.LemmaAnnotation.class);
//                lemma.append(" ").append(originalWord);
//            }
//        }
//        return reLemma(lemma.toString()).toLowerCase();
//    }
//
//    // 因为斯坦福会对标点符号前后加上空格，因此，需要作一定的处理。比如：ganoderma lucidum ( leyss . ex fr . ) karst -> ganoderma lucidum (leyss.ex fr) karst
//    public static String reLemma(String str) {
//        str = str.replace(" / ", "/")
//                .replace(" , ", ",")
//                .replace(" ' ", "'")
//                .replace(" '", "'")
//                .replace(" + ", "+")
//                .replace(" ; ", ";")
//                .replace(" ;", ";")
//                .replace(" ^ ", "^")
//                .replace(" ] ", "] ")
//                .replace(" } ", "} ")
//                .replace(" [ ", " [")
//                .replace(" { ", " {")
//                .replace(" \\ ", "\\")
//                .replace(" : ", ":")
//                .replace(" $ ", " $")
//                .replace(" % ", "% ")
//                .replace(" # ", "#")
//                .replace(" #", "#")
//                .replace(" - ", "-")
//                .replace(" . ", ".")
//                .replace("( ", "(")
//                .replace(" )", ")")
//                .replace("()", " ")
//                .replace(".)", ")")
//                .replaceAll(" +", " ").trim();
//        if (str.startsWith("(") && !str.contains(")")) {
//            str = str.substring(1);
//        }
//        if (str.endsWith(")") && !str.contains("(")) {
//            str = str.substring(0, str.length() - "(".length());
//        }
//        // 因为斯坦福会对引号前后加上引号，因此需要还原。比如：ch " ildren's hos " pi " t " al -> ch "ildren's hos" pi "t" al
//        if (str.contains("\"")) {
//            List<String> list = Arrays.asList(str.split("\""));
//            StringBuilder temp = new StringBuilder();
//            for (int i = 0; i < list.size(); i++) {
//                if (i % 2 == 0) {
//                    temp.append(list.get(i).trim()).append(" \"");
//                } else {
//                    temp.append(list.get(i).trim()).append("\" ");
//                }
//            }
//            if (!str.endsWith("\"") && temp.toString().endsWith("\"")) {
//                temp = new StringBuilder(temp.substring(0, temp.length() - "\"".length()));
//            }
//            str = temp.toString().trim();
//        }
//        return str.trim();
//    }
//
//
//}
